﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

namespace CSLua
{
	// Token: 0x0200001B RID: 27
	public static class CSLMix
	{
		// Token: 0x060000DC RID: 220 RVA: 0x0000569B File Offset: 0x0000389B
		public static string luaIdentifier(this FieldReference _this)
		{
			bool isPrivate = _this.Resolve().IsPrivate;
			return BuilderUtils.toIdentifier(_this.Name);
		}


		// Token: 0x060000DE RID: 222 RVA: 0x000056E4 File Offset: 0x000038E4
		public static string luaLocalFullName(this VariableDefinition _this)
		{
			if (string.IsNullOrEmpty(_this.Name))
			{
				return "var_" + _this.Index;
			}
			return _this.Name;
		}

		// Token: 0x060000DF RID: 223 RVA: 0x0000570F File Offset: 0x0000390F
		public static string luaLocalFullName(this ParameterReference _this)
		{
			if (_this.Index == -1)
			{
				return "self";
			}
			if (_this.ParameterType.FullName == BuildConfig.LuaArgsType)
			{
				return "...";
			}
			return _this.Name;
		}

		// Token: 0x060000E0 RID: 224 RVA: 0x00005743 File Offset: 0x00003943
		public static string luaIdentifier(this MemberReference _this)
		{
			return BuilderUtils.toIdentifier(_this.Name);
		}

		// Token: 0x060000E1 RID: 225 RVA: 0x00005750 File Offset: 0x00003950
		public static bool isEquals(this MemberReference _this, MemberReference _other)
		{
			return _this.FullName == _other.FullName;
		}

		// Token: 0x060000E2 RID: 226 RVA: 0x00005764 File Offset: 0x00003964
		public static CustomAttribute getAttribute(this Mono.Cecil.ICustomAttributeProvider _this, string attributeName)
		{
			return _this.CustomAttributes.FirstOrDefault((CustomAttribute x) => x.AttributeType.FullName == attributeName);
		}

		// Token: 0x060000E3 RID: 227 RVA: 0x00005798 File Offset: 0x00003998
		public static bool hasAttributes(this Mono.Cecil.ICustomAttributeProvider _this, IEnumerable<string> attrs)
		{
			return _this.CustomAttributes.Any((CustomAttribute x) => attrs.Contains(x.AttributeType.FullName));
		}

		// Token: 0x060000E4 RID: 228 RVA: 0x000057CC File Offset: 0x000039CC
		public static bool hasAttributes(this Mono.Cecil.ICustomAttributeProvider _this, string attributeName)
		{
			return _this.CustomAttributes.Any((CustomAttribute x) => x.AttributeType.FullName == attributeName);
		}

		// Token: 0x060000E5 RID: 229 RVA: 0x000057FD File Offset: 0x000039FD
		public static bool isForceUnvirtual(this TypeReference t)
		{
			return t.Resolve().hasAttributes(BuildConfig.unvirtualAttribute);
		}
		private static Dictionary<AssemblyDefinition, bool> _assemblyLuaTypeCheck = new Dictionary<AssemblyDefinition, bool>();  
		// Token: 0x060000E6 RID: 230 RVA: 0x00005810 File Offset: 0x00003A10
		public static bool isLuaType(this TypeReference type)
		{
			if (type.IsGenericParameter)
			{
				return false;
			}
			TypeDefinition typeDef = type.Resolve();
			if (typeDef == null)
			{
				return false;
			}
			if(!_assemblyLuaTypeCheck.TryGetValue(typeDef.Module.Assembly,out var isLua))
            {
				CustomAttribute attribute = typeDef.Module.Assembly.getAttribute(typeof(AssemblyConfigurationAttribute).FullName);
				isLua = attribute != null && attribute.ConstructorArguments.Count > 0 && attribute.ConstructorArguments.FirstOrDefault().Value == "CSLua";
				_assemblyLuaTypeCheck[typeDef.Module.Assembly] = isLua;
			}
			return isLua;
		}

		// Token: 0x060000E7 RID: 231 RVA: 0x00005886 File Offset: 0x00003A86
		public static bool isOutType(this TypeReference type)
		{
			return type.isLuaType() && type.Resolve().hasAttributes(CSLStub.OutAttribute);
		}

		// Token: 0x060000E8 RID: 232 RVA: 0x000058A4 File Offset: 0x00003AA4
		public static bool isDelegate(this TypeReference t)
		{
			for (TypeDefinition type = t.Resolve(); type != null; type = type.BaseType.Resolve())
			{
				if (type.FullName == typeof(Delegate).FullName)
				{
					return true;
				}
				if (type.BaseType == null)
				{
					return false;
				}
			}
			return false;
		}

		// Token: 0x060000E9 RID: 233 RVA: 0x000058F4 File Offset: 0x00003AF4
		public static string luaIdentifier(this TypeReference _this)
		{
			string name = _this.Name;
			int index = name.IndexOf('`');
			if (index > 0)
			{
				name = name.Substring(0, index);
			}
			return BuilderUtils.toIdentifier(name);
		}

		// Token: 0x060000EA RID: 234 RVA: 0x00005924 File Offset: 0x00003B24
		public static string luaGlobalIdentifier(this TypeReference _this)
		{
			return _this.FullName;
		}

		// Token: 0x060000EB RID: 235 RVA: 0x0000592C File Offset: 0x00003B2C
		public static bool isTypeOf<T>(this TypeReference _this)
		{
			return _this.FullName == typeof(T).FullName;
		}

		// Token: 0x060000EC RID: 236 RVA: 0x00005948 File Offset: 0x00003B48
		public static bool isSubTypeOf<T>(this TypeReference _this)
		{
			return _this.isSubTypeOf(typeof(T).FullName);
		}

		// Token: 0x060000ED RID: 237 RVA: 0x00005960 File Offset: 0x00003B60
		public static bool isSubTypeOf(this TypeReference _this, string fullName)
		{
			if (_this == null)
			{
				return false;
			}
			if (_this.FullName == fullName)
			{
				return true;
			}
			TypeDefinition type = _this.Resolve();
			if (type.BaseType.isSubTypeOf(fullName))
			{
				return true;
			}
			using (Collection<TypeReference>.Enumerator enumerator = type.Interfaces.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current.isSubTypeOf(fullName))
					{
						return true;
					}
				}
			}
			return false;
		}

		// Token: 0x060000EE RID: 238 RVA: 0x000059E8 File Offset: 0x00003BE8
		public static bool isBasicType(this TypeReference _this)
		{
			return _this.isTypeOf<string>() || _this.isNumber() || _this.isTypeOf<bool>();
		}

		// Token: 0x060000EF RID: 239 RVA: 0x00005A02 File Offset: 0x00003C02
		public static bool isNumber(this TypeReference _this)
		{
			return _this.isIntType() || _this.isFloatType();
		}

		// Token: 0x060000F0 RID: 240 RVA: 0x00005A14 File Offset: 0x00003C14
		public static bool isIntType(this TypeReference _this)
		{
			return _this.isSignedIntType() || _this.isUnsignedIntType();
		}

		// Token: 0x060000F1 RID: 241 RVA: 0x00005A26 File Offset: 0x00003C26
		public static bool isSignedIntType(this TypeReference _this)
		{
			return _this.isTypeOf<byte>() || _this.isTypeOf<short>() || _this.isTypeOf<int>() || _this.isTypeOf<long>() || _this.isTypeOf<sbyte>();
		}

		// Token: 0x060000F2 RID: 242 RVA: 0x00005A50 File Offset: 0x00003C50
		public static bool isUnsignedIntType(this TypeReference _this)
		{
			return _this.isTypeOf<char>() || _this.isTypeOf<ushort>() || _this.isTypeOf<uint>() || _this.isTypeOf<ulong>();
		}

		// Token: 0x060000F3 RID: 243 RVA: 0x00005A72 File Offset: 0x00003C72
		public static bool isFloatType(this TypeReference _this)
		{
			return _this.isTypeOf<float>() || _this.isTypeOf<double>();
		}

		// Token: 0x060000F4 RID: 244 RVA: 0x00005A84 File Offset: 0x00003C84
		public static bool isCtor(this MethodReference _this)
		{
			return _this.Name == ".ctor";
		}

		// Token: 0x060000F5 RID: 245 RVA: 0x00005A96 File Offset: 0x00003C96
		public static bool isSetter(this MethodReference _this)
		{
			return _this.Name.StartsWith("set_");
		}

		// Token: 0x060000F6 RID: 246 RVA: 0x00005AA8 File Offset: 0x00003CA8
		public static bool isGetter(this MethodReference _this)
		{
			return _this.Name.StartsWith("get_");
		}

		// Token: 0x060000F7 RID: 247 RVA: 0x00005ABA File Offset: 0x00003CBA
		public static string toPropertyIdentifier(this MethodReference _this)
		{
			if (!_this.isGetter() && !_this.isSetter())
			{
				throw new Exception();
			}
			return BuilderUtils.toIdentifier(_this.Name.Substring("get_".Length));
		}

		// Token: 0x060000F8 RID: 248 RVA: 0x00005AEC File Offset: 0x00003CEC
		public static bool isStaticCtor(this MethodReference _this)
		{
			return _this.Name == ".cctor";
		}
	}
}
